import numpy as np
import os

import sklearn
import torch.nn as nn
import torch
from PIL import ImageOps, Image
from sklearn.metrics import confusion_matrix
from skimage import filters
from sklearn.metrics import explained_variance_score

# from utils.evaluation_metrics3D import metrics_3d, Dice


def threshold(image):
    # t = filters.threshold_otsu(image, nbins=256)
    image[image >= 127] = 255
    image[image < 127] = 0
    return image


def numeric_score(pred, gt):
    FP = np.float(np.sum((pred == 255) & (gt == 0)))
    FN = np.float(np.sum((pred == 0) & (gt == 255)))
    TP = np.float(np.sum((pred == 255) & (gt == 255)))
    TN = np.float(np.sum((pred == 0) & (gt == 0)))
    return FP, FN, TP, TN


def metrics(pred, label, batch_size):
    # pred = torch.argmax(pred, dim=1) # for CE Loss series
    outputs = (pred.data.cpu().numpy() * 255).astype(np.uint8)
    labels = (label.data.cpu().numpy() * 255).astype(np.uint8)
    outputs = outputs.squeeze(1)  # for MSELoss()
    # print(outputs.shape)
    labels = labels.squeeze(1)  # for MSELoss()
    # print(labels.shape)
    outputs = threshold(outputs)  # for MSELoss()在二值化之前都是概率值

    Acc, SEn, Fdr, Dice = 0., 0., 0., 0.
    for i in range(batch_size):
        img = outputs[i, :, :]
        gt = labels[i, :, :]
        acc, sen, fdr, dice = get_acc(img, gt)
        # print("acc, sen, fdr, dice",acc, sen, fdr, dice)
        Acc += acc
        SEn += sen
        Fdr += fdr
        Dice += dice

    return Acc / batch_size, SEn / batch_size, Fdr / batch_size, Dice / batch_size


def metrics_auc(pred, label):
    # pred = pred.cpu()
    pred = pred.data.cpu().numpy()
    label = label.data.cpu().numpy()
    pred = pred.flatten()
    label = label.flatten()
    # print(label.shape, label.dtype, label.min(), label.max())
    # print(pred.shape, pred.dtype, pred.min(), pred.max())
    test_auc = sklearn.metrics.roc_auc_score(label, pred)
    return test_auc




def get_acc(image, label):
    image = threshold(image)

    FP, FN, TP, TN = numeric_score(image, label)
    # print("FP, FN, TP, TN:",FP, FN, TP, TN)
    acc = (TP + TN) / (TP + FN + TN + FP + 1e-10)
    sen = (TP) / (TP + FN + 1e-10)
    fdr = (FP) / (FP + TP + 1e-10)
    dice = 2 * TP / (FP + 2 * TP + FN + 1e-10)

    return acc, sen, fdr, dice
